<?php
/***********************************************************************
 * @package    IvanEngine
 * @subpackage Core
 * @author     Ivan <ivanzx@msn.com>
 * @created    2010-05-12
 ***********************************************************************/
if(defined("IVANENGINE_CORE_REQUEST"))
    die("Redefinition macro in :".__FILE__."(".__LINE__.")");
define("IVANENGINE_CORE_REQUEST", true);

require_once (dirname(__FILE__).'/Common.php');

class CRequest extends CEventSingleton
{
    const MT_GET            = 'GET';
    const MT_POST           = 'POST';
    const MT_PUT            = 'PUT';
    const MT_DELETE         = 'DELETE';
    const MT_HEAD           = 'HEAD';
    
    const OT_Formats        = 'formats';
    const OT_PathInfoKey    = 'path_info_key';
    const OT_PathInfoArray  = 'path_info_array';
    const OT_NoScriptName   = 'no_script_name';
    const OT_RelativeUrlRoot= 'relative_url_root';

    const RC_PathInfo       = 'RC_PathInfo';
    const RC_Prefix         = 'RC_Prefix';
    const RC_Method         = 'RC_Method';
    const RC_Format         = 'RC_Format';
    const RC_Host           = 'RC_Host';
    const RC_IsSecure       = 'RC_IsSecure';
    const RC_RequestUri     = 'RC_RequestUri';

    protected
        $m_method               = null,
        $m_options              = array(),
        $m_parameters           = null,
        $m_attributes           = null,
        $m_languages            = null, // brower language
        $m_charsets             = null, // Accept-Charset of current request
        $m_acceptableContentTypes= null,// Accept of current request
        $m_pathInfoArray        = null, // $_SERVER or $_ENV reference
        $m_relativeUrlRoot      = null,
        $m_getParameters        = null,
        $m_postParameters       = null,
        $m_requestParameters    = null,
        $m_formats              = array(),
        $m_format               = null,
        $m_fileArrayFixed       = false; // Set the file data for only one
    
    static protected $m_this= null;
    
    public function __construct()
    {
        parent::__construct();
    }

    public function __destruct()
    {
        unset($this->m_method);
        unset($this->m_options);
        unset($this->m_parameters);
        unset($this->m_attributes);
        unset($this->m_languages);
        unset($this->m_charsets);
        unset($this->m_acceptableContentTypes);
        unset($this->m_pathInfoArray);
        unset($this->m_relativeUrlRoot);
        unset($this->m_getParameters);
        unset($this->m_postParameters);
        unset($this->m_requestParameters);
        unset($this->m_formats);
        unset($this->m_format);
        unset($this->m_fileArrayFixed);
        parent::__destruct();
    }
    
    static public function Get()
    {
        if( self::$m_this == null )
        {
            parent::StartSingleton();
            self::$m_this = new CRequest($parameters, $attributes, $options);
            parent::EndSingleton();
        }
        return self::$m_this;
    }
    
    /**
    * Initializes this CRequest.
    * @param  sfEventDispatcher $dispatcher  An sfEventDispatcher instance
    * @param  array             $parameters  An associative array of initialization parameters
    * @param  array             $attributes  An associative array of initialization attributes
    * @param  array             $options     An associative array of options
    * @return bool true, if initialization completes successfully, otherwise false
    */
    public function Initialize(array $parameters = array(), array $attributes = array(), array $options = array())
    {
        $this->m_options = $options;
    
        // initialize parameter and attribute holders
        $this->m_parameters     = new CMap();
        $this->m_attributes     = new CMap();
    
        $this->m_parameters->AppendArray($parameters);
        $this->m_attributes->AppendArray($attributes);
        
        // GET parameters
        $this->m_getParameters  = get_magic_quotes_gpc() ? CHelper::StripSlashes($_GET) : $_GET;
        $this->m_parameters->AppendArray($this->m_getParameters);
    
        // POST parameters
        $this->m_postParameters = get_magic_quotes_gpc() ? CHelper::StripSlashes($_POST) : $_POST;
        $this->m_parameters->AppendArray($this->m_postParameters);
    
        if (isset($_SERVER['REQUEST_METHOD']))
        {
            $this->SetMethod($_SERVER['REQUEST_METHOD']);
        }
        else
        {
            // set the default method
            $this->SetMethod(self::GET);
        }
    
        if (isset($this->m_options[self::OT_Formats]))
        {
            foreach ($this->m_options[self::OT_Formats] as $format => $mimeTypes)
            {
                $this->SetFormat($format, $mimeTypes);
            }
        }
    
        if (!isset($this->m_options[self::OT_PathInfoKey]))
        {
            $this->m_options[self::OT_PathInfoKey] = 'PATH_INFO';
        }
    
        if (!isset($this->m_options[self::OT_PathInfoArray]))
        {
            $this->m_options[self::OT_PathInfoArray] = 'SERVER';
        }
    
        // additional parameters
        $this->m_requestParameters = $this->ParseRequestParameters();
        if( $this->m_requestParameters )
            $this->m_parameters->AppendArray($this->m_requestParameters);
    
        $this->FixParameters();
    }
    
    /**
    * Gets the request method.
    *
    * @return string The request method
    */
    public function GetMethod()
    {
        return $this->m_method;
    }
    
    /**
    * Sets the request method.
    *
    * @param string $method  The request method
    *
    * @throws <b>CException</b> - If the specified request method is invalid
    */
    public function SetMethod($method)
    {
        if (!in_array(CString::StrToUpper($method), array(
            self::MT_GET, self::MT_POST, self::MT_PUT, self::MT_DELETE, self::MT_HEAD)))
        {
           throw new CException('Invalid request method: %s.', $method);
        }
    
        $this->m_method = CString::StrToUpper($method);
    }
    
    /**
    * Retrieves the parameters for the current request.
    *
    * @return CMap The parameter
    */
    public function & GetParameters()
    {
        return $this->m_parameters;
    }
    
    /**
    * Retrieves a paramater for the current request.
    *
    * @param string $name     Parameter name
    * @param string $default  Parameter default value
    *
    */
    public function GetParameter($name, $default = null)
    {
        $result    = $this->m_parameters->Get($name);
        if( !$result )
           return $default;
        return $result;
    }

    /**
    * Indicates whether or not a parameter exist for the current request.
    *
    * @param  string $name  Parameter name
    *
    * @return bool true, if the paramater exists otherwise false
    */
    public function HasParameter($name)
    {
        return $this->m_parameters->Has($name);
    }

    /**
    * Sets a parameter for the current request.
    *
    * @param string $name   Parameter name
    * @param string $value  Parameter value
    *
    */
    public function SetParameter($name, $value)
    {
        $this->m_parameters->Set($name, $value);
    }
    
    /**
    * Retrieves the attributes holder.
    *
    * @return sfParameterHolder The attribute holder
    */
    public function & GetAttributes()
    {
        return $this->m_attributes;
    }
  
    /**
    * Retrieves an attribute from the current request.
    *
    * @param  string $name     Attribute name
    * @param  string $default  Default attribute value
    *
    * @return mixed An attribute value
    */
    public function GetAttribute($name, $default = null)
    {
        $result    = $this->m_attributes->Get($name);
        if( !$result )
           return $default;
        return $result;
    }
    
    /**
    * Indicates whether or not an attribute exist for the current request.
    *
    * @param  string $name  Attribute name
    *
    * @return bool true, if the attribute exists otherwise false
    */
    public function HasAttribute($name)
    {
        return $this->m_attributes->Has($name);
    }

    /**
    * Sets an attribute for the request.
    *
    * @param string $name   Attribute name
    * @param string $value  Value for the attribute
    *
    */
    public function SetAttribute($name, $value)
    {
        $this->m_attributes->Set($name, $value);
    }
    
    /**
    * Retrieves the uniform resource identifier for the current web request.
    *
    * @return string Unified resource identifier
    */
    public function GetURI()
    {
        $pathArray = $this->GetPathInfoArray();

        // for IIS with rewrite module (IIFR, ISAPI Rewrite, ...)
        if ('HTTP_X_REWRITE_URL' == $this->m_options[self::OT_PathInfoKey])
        {
            $uri = isset($pathArray['HTTP_X_REWRITE_URL']) ? $pathArray['HTTP_X_REWRITE_URL'] : '';
        }
        else
        {
            $uri = isset($pathArray['REQUEST_URI']) ? $pathArray['REQUEST_URI'] : '';
        }

        return $this->IsAbsUri() ? $uri : $this->GetUriPrefix().$uri;
    }
    
    /**
    * See if the client is using absolute uri
    *
    * @return boolean true, if is absolute uri otherwise false
    */
    public function IsAbsUri()
    {
        $pathArray = $this->GetPathInfoArray();

        return isset($pathArray['REQUEST_URI']) ? preg_match('/^http/', $pathArray['REQUEST_URI']) : false;
    }
    
    /**
    * Returns Uri prefix, including protocol, hostname and server port.
    *
    * @return string Uniform resource identifier prefix
    */
    public function GetUriPrefix()
    {
    $pathArray = $this->GetPathInfoArray();
    if ($this->IsSecure())
    {
        $standardPort = '443';
        $protocol = 'https';
    }
    else
    {
        $standardPort = '80';
        $protocol = 'http';
    }

    $host = explode(":", $this->GetHost());
    if (count($host) == 1)
    {
        $host[] = isset($pathArray['SERVER_PORT']) ? $pathArray['SERVER_PORT'] : '';
    }

    if ($host[1] == $standardPort || empty($host[1]))
    {
        unset($host[1]);
    }

    return $protocol.'://'.implode(':', $host);;
    }

    /**
    * Retrieves the path info for the current web request.
    *
    * @return string Path info
    */
    public function GetPathInfo()
    {
        $pathInfo = '';

        $pathArray = $this->GetPathInfoArray();

        // simulate PATH_INFO if needed
        $sf_path_info_key = $this->m_options[self::OT_PathInfoKey];
        if (!isset($pathArray[$sf_path_info_key]) || !$pathArray[$sf_path_info_key])
        {
            if (isset($pathArray['REQUEST_URI']))
            {
                $script_name = $this->GetScriptName();
                $uri_prefix = $this->IsAbsUri() ? $this->GetUriPrefix() : '';
                $pathInfo = preg_replace('/^'.preg_quote($uri_prefix, '/').'/','',$pathArray['REQUEST_URI']);
                $pathInfo = preg_replace('/^'.preg_quote($script_name, '/').'/', '', $pathInfo);
                $prefix_name = preg_replace('#/[^/]+$#', '', $script_name);
                $pathInfo = preg_replace('/^'.preg_quote($prefix_name, '/').'/', '', $pathInfo);
                $pathInfo = preg_replace('/\??'.preg_quote($pathArray['QUERY_STRING'], '/').'$/', '', $pathInfo);
            }
        }
        else
        {
            $pathInfo       = $pathArray[$sf_path_info_key];
            $relativeUrlRoot= $this->GetRelativeUrlRoot();
            if ($relativeUrlRoot)
            {
                $pathInfo = preg_replace('/^'.str_replace('/', '\\/', $relativeUrlRoot).'\//', '', $pathInfo);
            }
        }

        // for IIS
        if (isset($_SERVER['SERVER_SOFTWARE']) && false !== stripos($_SERVER['SERVER_SOFTWARE'], 'iis') && $pos = stripos($pathInfo, '.php'))
        {
            $pathInfo = substr($pathInfo, $pos + 4);
        }

        if (!$pathInfo)
        {
            $pathInfo = '/';
        }

        return $pathInfo;
    }

    public function GetPathInfoPrefix()
    {
        $prefix = $this->GetRelativeUrlRoot();

        if (!isset($this->m_options[self::OT_NoScriptName]) || !$this->m_options[self::OT_NoScriptName])
        {
          $scriptName = $this->GetScriptName();
          $prefix = is_null($prefix) ? $scriptName : $prefix.'/'.basename($scriptName);
        }

        return $prefix;
    }
    
    public function GetGetParameters()
    {
        return $this->m_getParameters;
    }

    public function GetPostParameters()
    {
        return $this->m_postParameters;
    }

    public function GetRequestParameters()
    {
        return $this->m_requestParameters;
    }

    public function AddRequestParameters($parameters)
    {
        $this->m_requestParameters = array_merge($this->m_requestParameters, $parameters);
        $this->GetParameters()->AppendArray($parameters);

        $this->FixParameters();
    }

    /**
    * Returns referer.
    *
    * @return string
    */
    public function GetReferer()
    {
        $pathArray = $this->GetPathInfoArray();

        return isset($pathArray['HTTP_REFERER']) ? $pathArray['HTTP_REFERER'] : '';
    }

    /**
    * Returns current host name.
    *
    * @return string
    */
    public function GetHost()
    {
        $pathArray = $this->GetPathInfoArray();

        return isset($pathArray['HTTP_X_FORWARDED_HOST']) ? $pathArray['HTTP_X_FORWARDED_HOST'] : (isset($pathArray['HTTP_HOST']) ? $pathArray['HTTP_HOST'] : '');
    }

    /**
    * Returns current script name.
    *
    * @return string
    */
    public function GetScriptName()
    {
        $pathArray = $this->GetPathInfoArray();

        return isset($pathArray['SCRIPT_NAME']) ? $pathArray['SCRIPT_NAME'] : (isset($pathArray['ORIG_SCRIPT_NAME']) ? $pathArray['ORIG_SCRIPT_NAME'] : '');
    }

    /**
    * Checks if the request method is the given one.
    *
    * @param  string $method  The method name
    *
    * @return bool true if the current method is the given one, false otherwise
    */
    public function IsMethod($method)
    {
        return strtoupper($method) == $this->GetMethod();
    }

    /**
    * Returns the preferred culture for the current request.
    *
    * @param  array  $cultures  An array of ordered cultures available
    *
    * @return string The preferred culture
    */
    public function GetPreferredCulture(array $cultures = null)
    {
        $preferredCultures = $this->GetLanguages();

        if (is_null($cultures))
        {
            return isset($preferredCultures[0]) ? $preferredCultures[0] : null;
        }

        if (!$preferredCultures)
        {
            return $cultures[0];
        }

        $preferredCultures = array_values(array_intersect($preferredCultures, $cultures));

        return isset($preferredCultures[0]) ? $preferredCultures[0] : $cultures[0];
    }

    /**
    * Gets a list of languages acceptable by the client browser
    *
    * @return array Languages ordered in the user browser preferences
    */
    public function GetLanguages()
    {
        if ($this->languages)
        {
            return $this->m_languages;
        }

        if (!isset($_SERVER['HTTP_ACCEPT_LANGUAGE']))
        {
            return array();
        }

        $languages = $this->SplitHttpAcceptHeader($_SERVER['HTTP_ACCEPT_LANGUAGE']);
        foreach ($languages as $lang)
        {
            if (strstr($lang, '-'))
            {
                $codes = explode('-', $lang);
                if ($codes[0] == 'i')
                {
                    // Language not listed in ISO 639 that are not variants
                    // of any listed language, which can be registerd with the
                    // i-prefix, such as i-cherokee
                    if (count($codes) > 1)
                    {
                        $lang = $codes[1];
                    }
                }
                else
                {
                    for ($i = 0, $max = count($codes); $i < $max; $i++)
                    {
                        if ($i == 0)
                        {
                            $lang = strtolower($codes[0]);
                        }
                        else
                        {
                            $lang .= '_'.strtoupper($codes[$i]);
                        }
                    }
                }
            }

            $this->m_languages[] = $lang;
        }

        return $this->m_languages;
    }

    /**
    * Gets a list of charsets acceptable by the client browser.
    *
    * @return array List of charsets in preferable order
    */
    public function GetCharsets()
    {
        if ($this->m_charsets)
        {
            return $this->m_charsets;
        }

        if (!isset($_SERVER['HTTP_ACCEPT_CHARSET']))
        {
            return array();
        }

        $this->m_charsets = $this->SplitHttpAcceptHeader($_SERVER['HTTP_ACCEPT_CHARSET']);

        return $this->m_charsets;
    }

    /**
    * Gets a list of content types acceptable by the client browser
    *
    * @return array Languages ordered in the user browser preferences
    */
    public function GetAcceptableContentTypes()
    {
        if ($this->acceptableContentTypes)
        {
            return $this->m_acceptableContentTypes;
        }

        if (!isset($_SERVER['HTTP_ACCEPT']))
        {
            return array();
        }

        $this->m_acceptableContentTypes = $this->SplitHttpAcceptHeader($_SERVER['HTTP_ACCEPT']);

        return $this->m_acceptableContentTypes;
    }

    /**
    * Returns true if the request is a XMLHttpRequest.
    *
    * It works if your JavaScript library set an X-Requested-With HTTP header.
    * Works with Prototype, Mootools, jQuery, and perhaps others.
    *
    * @return bool true if the request is an XMLHttpRequest, false otherwise
    */
    public function IsXmlHttpRequest()
    {
        return ($this->GetHttpHeader('X_REQUESTED_WITH') == 'XMLHttpRequest');
    }

    public function GetHttpHeader($name, $prefix = 'http')
    {
        if ($prefix)
        {
            $prefix = strtoupper($prefix).'_';
        }

        $name = $prefix.strtoupper(strtr($name, '-', '_'));

        $pathArray = $this->GetPathInfoArray();

        return isset($pathArray[$name]) ? CHelper::StripSlashes($pathArray[$name]) : null;
    }

    /**
    * Gets a cookie value.
    *
    * @param  string $name          Cookie name
    * @param  string $defaultValue  Default value returned when no cookie with given name is found
    *
    * @return mixed
    */
    public function GetCookie($name, $defaultValue = null)
    {
        $retval = $defaultValue;

        if (isset($_COOKIE[$name]))
        {
            $retval = get_magic_quotes_gpc() ? CHelper::StripSlashes($_COOKIE[$name]) : $_COOKIE[$name];
        }

        return $retval;
    }

    /**
    * Returns true if the current request is secure (HTTPS protocol).
    *
    * @return boolean
    */
    public function IsSecure()
    {
        $pathArray = $this->GetPathInfoArray();

        return (
            (isset($pathArray['HTTPS']) && (strtolower($pathArray['HTTPS']) == 'on' || $pathArray['HTTPS'] == 1))
            ||
            (isset($pathArray['HTTP_SSL_HTTPS']) && (strtolower($pathArray['HTTP_SSL_HTTPS']) == 'on' || $pathArray['HTTP_SSL_HTTPS'] == 1))
            ||
            (isset($pathArray['HTTP_X_FORWARDED_PROTO']) && strtolower($pathArray['HTTP_X_FORWARDED_PROTO']) == 'https')
        );
    }

    /**
    * Retrieves relative root url.
    *
    * @return string URL
    */
    public function GetRelativeUrlRoot()
    {
        if ($this->m_relativeUrlRoot === null )
        {
            if (!isset($this->m_options[self::OT_RelativeUrlRoot]))
            {
                $this->m_relativeUrlRoot = preg_replace('#/[^/]+\.php5?$#', '', $this->GetScriptName());
            }
            else
            {
                $this->m_relativeUrlRoot = $this->m_options[self::OT_RelativeUrlRoot];
            }
        }

        return $this->m_relativeUrlRoot;
    }

    /**
    * Sets the relative root url for the current web request.
    *
    * @param string $value  Value for the url
    */
    public function SetRelativeUrlRoot($value)
    {
        $this->m_relativeUrlRoot = $value;
    }

    /**
    * Splits an HTTP header for the current web request.
    *
    * @param string $header  Header to split
    */
    public function SplitHttpAcceptHeader($header)
    {
        $values = array();
        foreach (array_filter(explode(',', $header)) as $value)
        {
            // Cut off any q-value that might come after a semi-colon
            $pos    = strpos($value, ';');
            if ($pos)
            {
                $q     = (float) trim(substr($value, $pos + 3));
                $value = trim(substr($value, 0, $pos));
            }   
            else
            {
                $q = 1;
            }

          $values[$value] = $q;
        }

        arsort($values);

        return array_keys($values);
    }

    /**
    * Returns the array that contains all request information ($_SERVER or $_ENV).
    *
    * This information is stored in the [sf_path_info_array] constant.
    *
    * @return  array Path information
    */
    public function GetPathInfoArray()
    {
        if (!$this->m_pathInfoArray)
        {
            // parse PATH_INFO
            switch ($this->m_options[self::OT_PathInfoArray])
            {
                case 'SERVER':
                    $this->m_pathInfoArray =& $_SERVER;
                    break;

                case 'ENV':
                default:
                    $this->m_pathInfoArray =& $_ENV;
          }
        }

        return $this->m_pathInfoArray;
    }

    /**
    * Gets the mime type associated with the format.
    *
    * @param  string $format  The format
    *
    * @return string The associated mime type (null if not found)
    */
    public function GetMimeType($format)
    {
        return isset($this->m_formats[$format]) ? $this->m_formats[$format][0] : null;
    }

    /**
    * Gets the format associated with the mime type.
    *
    * @param  string $mimeType  The associated mime type
    *
    * @return string The format (null if not found)
    */
    public function GetFormat($mimeType)
    {
        foreach ($this->m_formats as $format => $mimeTypes)
        {
            if (in_array($mimeType, $mimeTypes))
            {
                return $format;
            }
        }

        return null;
    }

    /**
    * Associates a format with mime types.
    *
    * @param string       $format     The format
    * @param string|array $mimeTypes  The associated mime types (the preferred one must be the first as it will be used as the content type)
    */
    public function SetFormat($format, $mimeTypes)
    {
        $this->m_formats[$format] = is_array($mimeTypes) ? $mimeTypes : array($mimeTypes);
    }

    /**
    * Sets the request format.
    *
    * @param string $format  The request format
    */
    public function SetRequestFormat($format)
    {
        $this->m_format = $format;
    }

    /**
    * Gets the request format.
    *
    * Here is the process to determine the format:
    *
    *  * format defined by the user (with SetRequestFormat())
    *  * sf_format request parameter
    *  * null
    *
    * @return string The request format
    */
    public function GetRequestFormat()
    {
        if (is_null($this->m_format))
        {
            $this->SetRequestFormat($this->GetParameter('sf_format'));
        }

        return $this->m_format;
    }

    /**
    * Retrieves an array of files.
    *
    * @param  string $key  A key
    * @return array  An associative array of files
    */
    public function GetFiles($key = null)
    {
        if (false === $this->m_fileArrayFixed)
        {
            $files = self::ConvertFileInformation($_FILES);
            $this->m_fileArrayFixed = true;
        }

        return is_null($key) ? $files : (isset($files[$key]) ? $files[$key] : array());
    }

    /**
    * Converts uploaded file array to a format following the $_GET and $POST naming convention.
    *
    * It's safe to pass an already converted array, in which case this method just returns the original array unmodified.
    *
    * @param  array $taintedFiles An array representing uploaded file information
    *
    * @return array An array of re-ordered uploaded file information
    */
    static public function ConvertFileInformation(array $taintedFiles)
    {
        $files = array();
        foreach ($taintedFiles as $key => $data)
        {
            $files[$key] = self::FixPhpFilesArray($data);
        }

            return $files;
        }

    static protected function FixPhpFilesArray($data)
    {
        $fileKeys = array('error', 'name', 'size', 'tmp_name', 'type');
        $keys = array_keys($data);
        sort($keys);

        if ($fileKeys != $keys || !isset($data['name']) || !is_array($data['name']))
        {
            return $data;
        }

        $files = $data;
        foreach ($fileKeys as $k)
        {
            unset($files[$k]);
        }
        foreach (array_keys($data['name']) as $key)
        {
            $files[$key] = self::FixPhpFilesArray(array(
                'error'    => $data['error'][$key],
                'name'     => $data['name'][$key],
                'type'     => $data['type'][$key],
                'tmp_name' => $data['tmp_name'][$key],
                'size'     => $data['size'][$key],
            ));
        }

        return $files;
    }

    /**
    * Returns the value of a GET parameter.
    *
    * @param  string $name     The GET parameter name
    * @param  string $default  The default value
    *
    * @return string The GET parameter value
    */
    public function GetGetParameter($name, $default = null)
    {
        if (isset($this->m_getParameters[$name]))
        {
            return $this->m_getParameters[$name];
        }
        else
        {
            return CHelper::GetArrayValueForPath($this->m_getParameters, $name, $default);
        }
    }

    /**
    * Returns the value of a POST parameter.
    *
    * @param  string $name     The POST parameter name
    * @param  string $default  The default value
    *
    * @return string The POST parameter value
    */
    public function GetPostParameter($name, $default = null)
    {
        if (isset($this->m_postParameters[$name]))
        {
            return $this->m_postParameters[$name];
        }
        else
        {
            return CHelper::GetArrayValueForPath($this->m_postParameters, $name, $default);
        }
    }

    /**
    * Returns the value of a parameter passed as a URL segment.
    *
    * @param  string $name     The parameter name
    * @param  string $default  The default value
    *
    * @return string The parameter value
    */
    public function GetUrlParameter($name, $default = null)
    {
        if (isset($this->m_requestParameters[$name]))
        {
            return $this->m_requestParameters[$name];
        }
        else
        {
            return CHelper::GetArrayValueForPath($this->m_requestParameters, $name, $default);
        }
    }

    /**
    * Returns the remote IP address that made the request.
    *
    * @return string The remote IP address
    */
    public function GetRemoteAddress()
    {
        $pathInfo = $this->GetPathInfoArray();

        return $pathInfo['REMOTE_ADDR'];
    }

    /**
    * Returns an array containing a list of IPs, the first being the client address
    * and the others the addresses of each proxy that passed the request. The address 
    * for the last proxy can be retrieved via GetRemoteAddress().
    *
    * This method returns null if no proxy passed this request. Note that some proxies
    * do not use this header, and act as if they were the client.
    *
    * @return string|null An array of IP from the client and the proxies that passed
    * the request, or null if no proxy was used.
    */
    public function GetForwardedFor()
    {
        $pathInfo = $this->GetPathInfoArray();

        if (empty($pathInfo['HTTP_X_FORWARDED_FOR']))
        {
            return null;
        }

        return explode(', ', $pathInfo['HTTP_X_FORWARDED_FOR']);
    }

    public function CheckCSRFProtection()
    {
        //$form = new sfForm();
        //$form->bind($form->isCSRFProtected() ? array($form->getCSRFFieldName() => $this->GetParameter($form->getCSRFFieldName())) : array());

        //if (!$form->isValid())
        //{
        //    throw $form->getErrorSchema();
        //}
    }

    /**
    * Parses the request parameters.
    *
    * This method notifies the request.filter_parameters event.
    *
    * @return array An array of request parameters.
    */
    protected function ParseRequestParameters()
    {
        //return $this->dispatcher->filter(new sfEvent($this, 'request.filter_parameters', $this->getRequestContext()), array())->getReturnValue();
        return array();
    }

    /**
    * Returns the request context used.
    *
    * @param array An array of values representing the current request
    */
    public function GetRequestContext()
    {
        return array(
              self::RC_PathInfo     => $this->GetPathInfo(),
              self::RC_Prefix       => $this->GetPathInfoPrefix(),
              self::RC_Method       => $this->GetMethod(),
              self::RC_Format       => $this->GetRequestFormat(),
              self::RC_Host         => $this->GetHost(),
              self::RC_IsSecure     => $this->IsSecure(),
              self::RC_RequestUri   => $this->GetUri(),
        );
    }

    protected function FixParameters()
    {
        // move symfony parameters to attributes (parameters prefixed with _sf_)
        //foreach ($this->m_parameters->getAll() as $key => $value)
        //{
        //    if (0 === stripos($key, '_sf_'))
        //    {
        //        $this->m_parameters->Remove($key);
        //        $this->SetAttribute(substr($key, 1), $value);
        //    }
        //}
    }
}

?>